﻿
/*************************** Taken from google direction dynamic-service page  ***************************************/		

function initialize() {
  //directionsDisplay = new google.maps.DirectionsRenderer();
  var stockholm = new google.maps.LatLng(59.32522, 18.07002); // not used now
  var myOptions = {
    zoom:7,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
  }
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  //directionsDisplay.setMap(map); 
  // Instantiate an info window to hold step text.
  // stepDisplay = new google.maps.InfoWindow();
}


/*************************** calculating and drawing the route on the map  ***************************************/		

function calcRoute() {

  var start = document.getElementById("from").value + 'Sweden';
  var end = document.getElementById("to").value + 'Sweden';
  if (start && end) {
	
	//Geocoding start address in order to add it to path steps:
	geocoder = new google.maps.Geocoder();
	geocoder.geocode( { 'address': start}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        startLatLng = results[0].geometry.location;
		//Geocoding end address in order to add it to path steps:
		geocoder.geocode( { 'address': end}, function(results, status) {
		if (status == google.maps.GeocoderStatus.OK) {
			endLatLng = results[0].geometry.location;
			
		    initialize();
			var request = {
			origin:start,
			destination:end,
			region: 'SE',
			travelMode: google.maps.DirectionsTravelMode.DRIVING
			};    

			var polyline = new google.maps.Polyline({
			path: [],
			strokeColor: '#FF0000',
			strokeWeight: 2
			}); 
			
			var directionsService = new google.maps.DirectionsService();
			directionsService.route(request, function(response, status) {
			  if (status == google.maps.DirectionsStatus.OK) {
				  var stepsArray = response.routes[0].legs[0].steps;
				  var bounds = new google.maps.LatLngBounds();
				  pathSteps = response.routes[0].overview_path;
				 
				  var legs = response.routes[0].legs;
				  for (i=0;i<legs.length;i++) {
					var steps = legs[i].steps;
					for (j=0;j<steps.length;j++) {
					  var nextSegment = steps[j].path;
					  for (k=0;k<nextSegment.length;k++) {
						polyline.getPath().push(nextSegment[k]);
						bounds.extend(nextSegment[k]);
					  }
					}
				  }
				  polyline.setMap(map);
				  map.fitBounds(bounds);
				  getDesiredSteps();
				  
				  
			  }
			  console.debug(desiredSteps);
			  
			});

		} else {
			alert("Ogiltig slutdestination. Förskök igen!");
	  }
	});
      } else {
        alert("Ogiltig startadress. Förskök igen!");
      }
	});
	
  } else {
    alert('Välj från- och tilladdress.')
  } 

	/**************************reseting category buttons*********************/
	for(var i=1; i<categoryArray.length; i++) {
        if (categoryArray[i].status == 'active') {
         categoryArray[i].changeStatus();
        }
      }
}

/*************************** Getting desried steps from the path array accroding to the radius value  ***************************************/		
 
function getDesiredSteps() {
  desiredSteps = [];
  var tempDistance = 0; //This variable is used to sum the distance between a certain step and the steps that follow,
                         //It is reset as long as the summed distance become more than the distance from route (radius)*2 - 500
  
	
	//adding startaddress as first element in pathSteps.
	desiredSteps.push(startLatLng);
	
	//console.debug(desiredSteps);
	//showStep(pathSteps[0]);
	// storing only points that are 1km or more from each other
	for (var i = 0; i < pathSteps.length-1; i++){
		//console.debug('the distance between ' + i + 'and ' + (i+1) + 'is ' + computeDistance(pathSteps[i], pathSteps[i+1]))
		tempDistance += computeDistance(pathSteps[i], pathSteps[i+1]);
		//console.debug(computeDistance(pathSteps[i], pathSteps[i+1]));
		if (tempDistance > radius) {
			desiredSteps.push(pathSteps[i+1]);
			tempDistance = 0;
		} 
  
	}
	//adding slutdestination as last lement in pathSteps.
	desiredSteps.push(endLatLng);
  
  console.debug('There are ' + desiredSteps.length + ' desired steps.');
  
}


/*************************** Attaching a marker object to a place object  ***************************************/		


function attachMarker(place,category) {
  
	//console.debug('drawing a place');
	var position = place.geometry.location;
	var image = new google.maps.MarkerImage(
	'images/markers/' + category + '-marker.png');
	
	var infoString = '<div id="info-string">' +
					 '<h1>' + place.name + '</h1>' +
					 '<span>' + place.vicinity + '<span>' + 
					 '</div>';
	var infowindow = new google.maps.InfoWindow({
    content: infoString
	});

      place.marker = new google.maps.Marker({
      position: position,
	  icon: image,
	  title: place.name
      });
	  
	  map.addMarker(place.marker);

	  google.maps.event.addListener(place.marker, 'click', function() {
		infowindow.open(map,place.marker);
	  });
}


/*************************** Calculating the distance between two points ***************************************/		

function computeDistance(point1, point2) {
 var distance = google.maps.geometry.spherical.computeDistanceBetween(point1, point2);
 return distance;
}


/*************************** finding the common elements between two arrays************************************/
 
 /* two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length(), b.length())
 */
function intersect_safe(a, b) {
  var ai=0, bi=0;
  var result = new Array();

  while( ai < a.length && bi < b.length )
  {
     if      (a[ai] < b[bi] ){ ai++; }
     else if (a[ai] > b[bi] ){ bi++; }
     else /* they're equal */
     {
       result.push(a[ai]);
       ai++;
       bi++;
     }
  }

  return result;
}



/*************************** Custom functions for clearing all map's markers ************************************/

google.maps.Map.prototype.markers = new Array();

google.maps.Map.prototype.addMarker = function(marker) {
    this.markers[this.markers.length] = marker;
};

google.maps.Map.prototype.getMarkers = function() {
    return this.markers
};

google.maps.Map.prototype.clearMarkers = function() {
    for(var i=0; i<this.markers.length; i++){
        this.markers[i].setMap(null);
    }
    this.markers = new Array();
}


/*************************** Updating markers attached to place object ************************************/

function updatePlaces() {
	console.debug('updating places');
	$('#toppstopp-list').empty();
	if (places.length > 0){
		map.clearMarkers();
		console.debug('There are ' + places.length + ' places.');
		removeDuplicates(places, thingsEqual);
		console.debug('There are ' + places.length + ' places.');
		console.debug('There are ' + map.markers.length + ' markers on the map.');
		for(var i=0; i<places.length; i++){
			places[i].marker.setMap(map);
			var li = '<li id =' + places[i].id + '>' + places[i].name + '</li>';
			$('#toppstopp-list').append(li);
		}
	}
	else if (activeCategories.length > 0) {
		//$('#toppstopp-list').text('Din sökning gav inga resultat.');
	$('#toppstopp-list').html('Inga resultat.');
	}
}

/*************************** removing places from the places array ***************************************/

function removePlaces(categoryName) {
	if(categoryName !='undefined') {
			var indx = activeCategories.indexOf(categoryName);
			activeCategories.splice(indx,1);
	}
	
	if (places.length>0) {
		for (var i=places.length; i>0; i--) {
			if (activeCategories.length > 0) {
				activeCategories.sort();
				places[i-1].types.sort();
				var commonCategories = intersect_safe(places[i-1].types, activeCategories);
				console.debug('commonCategories are:' + commonCategories);
				if(commonCategories.length == 0) {
					places[i-1].marker.setMap(null);
					places.splice(i-1,1);
				}
			}
			else {
					places[i-1].marker.setMap(null);
					places.splice(i-1,1);
			}
			
		}
		
	}
}


/*************************** Extending the array object by adding some functions ************************************/
			
Array.prototype.unique = function() {
	var o = {}, i, l = this.length, r = [];
	for(i=0; i<l;i+=1) {
		o[this[i]] = this[i];
	}
	for(i in o) r.push(o[i]);
	return r;
}

Array.prototype.compare = function(arr) {
    if (arr.length == 0) return false;
    for (var i = 0; i < arr.length; i++) {
        if (this[i].compare) { 
            if (!this[i].compare(arr[i])) return false;
        }
        if (this[i] !== arr[i]) return false;
    }
    return true;
}


/*************************** Plotting items related to all active categories in the list and markers on the map ************************************/
function plot() {

	setTimeout(function(){
		
		updatePlaces();
		plot();
		console.debug('activeCategories are: ' + activeCategories);
	
	}, 4000);

} 


/**************************** The three functions below are used to find and eliminate duplicates in an array that contain objects ************************************/

function arrayContains(arr, val, equals) {
    var i = arr.length;
    while (i--) {
        if ( equals(arr[i], val) ) {
            return true;
        }
    }
    return false;
}

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, j, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arrayContains(arr, val, equals)) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.id === thing2.id;
}

